package com.c5p1ng.core.generator.bank;

import com.c5p1ng.core.generator.base.GenericGenerator;
import com.c5p1ng.core.util.StrUtil;

import java.util.Date;
import java.util.Random;

/**
 * 银行卡生成器
 *
 * @author c5p1ng
 */
public class BankCardNumberGenerator extends GenericGenerator {
    private static GenericGenerator instance = new BankCardNumberGenerator();

    private BankCardNumberGenerator() {
    }

    public static GenericGenerator getInstance() {
        return instance;
    }

    public String generate() {
        Random random = this.getRandomInstance();
        Integer prev = 622126 + random.nextInt(800);
        return generateByPrefix(prev);
    }

    public static String generateByPrefix(Integer prefix) {
        Random random = new Random((new Date()).getTime());
        String bardNo = prefix + StrUtil.leftPad(random.nextInt(999999999) + "", 9, "0");
        char[] chs = bardNo.trim().toCharArray();
        int luhmSum = 0;
        int i = chs.length - 1;

        for(int j = 0; i >= 0; ++j) {
            int k = chs[i] - 48;
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }

            luhmSum += k;
            --i;
        }

        char checkCode = luhmSum % 10 == 0 ? 48 : (char)(10 - luhmSum % 10 + 48);
        return bardNo + checkCode;
    }

    public static String generate(BankNameEnum bankName, BankCardTypeEnum cardType) {
        Integer[] candidatePrefixes = null;
        if (cardType == null) {
            candidatePrefixes = bankName.getAllCardPrefixes();
        } else {
            switch (cardType) {
                case DEBIT:
                    candidatePrefixes = bankName.getDebtCardPrefixes();
                    break;
                case CREDIT:
                    candidatePrefixes = bankName.getCreditCardPrefixes();
            }
        }

        if (candidatePrefixes != null && candidatePrefixes.length != 0) {
            Integer prefix = candidatePrefixes[(new Random()).nextInt(candidatePrefixes.length)];
            return generateByPrefix(prefix);
        } else {
            throw new RuntimeException("没有该银行的相关卡号信息");
        }
    }
}
